package kr.pe.asuraho;

import static kr.pe.asuraho.StaticMethods.capitalize;
import static kr.pe.asuraho.StaticMethods.nvl;

import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.ibatis.session.SqlSession;

public class BaseServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	public BaseServlet() {
		super();
	}

	@SuppressWarnings("unchecked")
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("UTF-8");
		String url = request.getRequestURI().replace("/", "");
		
		String className = capitalize(url.substring(0, url.indexOf(".do")));
		String methodName = nvl(request.getParameter("method"));
		
System.out.println(className + "." + methodName);
System.out.println(bindParameter(request.getParameterMap()));

		Class<?> cls;
		Method method;
		SqlSession sqlSession = null;
		Map<String, Object> userInfo = null;
		try {
			
			// 세션체크
			if(!("Login.main".equals(className+"."+methodName) || "Login.loginForm".equals(className+"."+methodName) || "Login.login".equals(className+"."+methodName))){
				
				HttpSession session = request.getSession();
				userInfo = (Map<String, Object>) session.getAttribute("ZHIBOGO_SESSION");
				if(userInfo == null || "".equals(nvl(userInfo.get("id")))){
					
					request.setAttribute("resultMessage", "로그인 하세요.");
					request.setAttribute("viewName", "/WEB-INF/jsp/login.jsp");
					
					RequestDispatcher view = request.getRequestDispatcher("main.jsp");
					view.forward(request, response);
					return;
				}
			}
			
			// 서비스 생성
			cls = Class.forName("kr.pe.asuraho.zhibogo." + className);
			Constructor<?> con = cls.getConstructor();
			Object obj = con.newInstance();

			// Mybatis 드러와~드러와~
			sqlSession = DBConn.getSqlSession();
			method = obj.getClass().getMethod("setSqlSession", SqlSession.class);
			method.invoke(obj, sqlSession);
			
			// 세션 드러와~드러와~
			method = obj.getClass().getMethod("setUserInfo", Map.class);
			method.invoke(obj, userInfo);
			
			// 파라메터 드러와~드러와~
			method = obj.getClass().getMethod("setParamMap", Map.class);
			method.invoke(obj, bindParameter(request.getParameterMap()));
			
			// request 드러와~드러와~
			method = obj.getClass().getMethod("setRequest", HttpServletRequest.class);
			method.invoke(obj, request);
			
			// response 드러와~드러와~
			method = obj.getClass().getMethod("setResponse", HttpServletResponse.class);
			method.invoke(obj, response);
			
			// Server 야~ 4885
			method = obj.getClass().getMethod(methodName);
			String viewName = nvl(method.invoke(obj));
			
			// Result Page 사람은 언제 죽는다고 생각한가? 독버섯 스푸? 마자용.... ㅠㅠ TODO ajax대응 일단 귀찬음
			RequestDispatcher view = null;
			if(viewName.indexOf("/WEB-INF/jsp/") != -1 && viewName.lastIndexOf(".jsp") != -1){
				view = request.getRequestDispatcher(viewName);
				view.forward(request, response);
			}else if(viewName.indexOf(".do") != -1){
				response.sendRedirect(viewName);
			}
			
			sqlSession.commit();
System.out.println("commit;");
		} catch (Exception e) {
			if (sqlSession != null) {
				sqlSession.rollback();
			}
e.printStackTrace();
			
			// 에라페이지 따라와~
			request.setAttribute("errorInfo", e.getMessage());
			RequestDispatcher view = request.getRequestDispatcher("/WEB-INF/jsp/error.jsp");
			view.forward(request, response);
			return;
			
		} finally {
		}
	}

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		this.doPost(request, response);
	}

	private Map<String, Object> bindParameter(Map<String, ?> param) {
		Map<String, Object> result = new HashMap<String, Object>();
		Iterator<String> it = param.keySet().iterator();
		String key = null;

		while (it.hasNext()) {
			key = nvl(it.next());

			String[] bindData = (String[]) param.get(key);
			if (bindData == null)
				continue;
			else if (bindData.length == 1) {
				result.put(key, nvl(bindData[0]));
			} else if (bindData.length > 1) {
				List<String> list = new ArrayList<String>();
				for (String str : bindData)
					list.add(str);
				result.put(key, list);
			}
		}

		return result;
	}
}